﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Dynamic;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using System.Web.Helpers;
using Newtonsoft.Json;

namespace MVCProject.API
{
    public class ApiAuthorizeAttribute:AuthorizeAttribute
    {
        protected override bool IsAuthorized(HttpActionContext actionContext)
        {
            //密钥
            string JwtKey = ConfigurationManager.AppSettings["JwtKey"];
            
            var authHeader = from t in actionContext.Request.Headers where t.Key == "Authorization" select t.Value.FirstOrDefault();
            if (authHeader != null)
            {
                string token = authHeader.FirstOrDefault();
                if (!string.IsNullOrEmpty(token))
                {
                    try
                    {
                        //JwtKey需要加密
                        IJsonSerializer serializer = new JsonNetSerializer();
                        IDateTimeProvider provider = new UtcDateTimeProvider();
                        IJwtValidator validator = new JwtValidator(serializer, provider);
                        IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                        IJwtAlgorithm algorithm = new HMACSHA256Algorithm();
                        IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);

                        //解密Token
                        var json = decoder.DecodeToObject<AuthInfo>(token, JwtKey, verify: true);
                        if (json != null)
                        {
                            //把数据存在RouteData里进行传递。
                            actionContext.RequestContext.RouteData.Values.Add("auth", json);
                            //验证一下IP
                            string ip = HttpContext.Current.Request.UserHostAddress.ToString();
                            //如果有其他的验证可以在此处理，比如是否过期，比如是不是验证是同一个IP请求等等……
                            ////判断是否过期
                            if (DateTime.Now.Ticks > json.Exp)
                            {
                                //票据超时
                                return false;
                            }
                            ////判断ip是否一致
                            //if (json.IP != ip)
                            //{
                            //    return false;
                            //}
                            //考虑角色授权的问题
                            //if (json.Roles!="管理员")
                            //{
                            //    // 403 角色没有权限
                            //    actionContext.Response.StatusCode = HttpStatusCode.Forbidden;
                            //    return false;
                            //}
                            return true;
                        }
                        else
                        {
                            //没有票据 401
                            actionContext.Response.StatusCode = HttpStatusCode.Unauthorized;
                            return false;
                        }
                       
                    }
                    catch (Exception ex)
                    {
                        return false;
                    }
                }
            }
            return false;
        }
        ///// <summary>
        ///// 重写实现处理授权失败时返回json,避免跳转登录页
        ///// </summary>
        protected override void HandleUnauthorizedRequest(HttpActionContext filterContext)
        {
            base.HandleUnauthorizedRequest(filterContext);

            var response = filterContext.Response = filterContext.Response ?? new HttpResponseMessage();
            //response.StatusCode = HttpStatusCode.Forbidden;
            //response.StatusCode = HttpStatusCode.Unauthorized;


            int code = (int)response.StatusCode;
            dynamic data = new ExpandoObject();
            data.code = -code;
            data.msg = code == 401 ? "服务端拒绝访问：你没有登录，或者登录已丢失！"
                : code == 403 ? "服务端拒绝访问：你没有足够的访问权限！"
                : "服务端拒绝访问：权限验证失败！";

            response.Content = new StringContent(JsonConvert.SerializeObject(data), Encoding.UTF8, "application/json");
        }
    }
}